package com.jxmcloud.business.cut.service.impl.user;

import cn.hutool.core.util.ObjectUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.google.common.collect.Lists;
import com.jxmcloud.business.cut.constants.CutSaveKey;
import com.jxmcloud.business.cut.dto.gm.AccountItemDto;
import com.jxmcloud.business.cut.dto.gm.ItemDto;
import com.jxmcloud.business.cut.dtoCommon.BagInfoDto;
import com.jxmcloud.business.cut.json.DataConfigGlobalGlobalLoader;
import com.jxmcloud.business.cut.json.DataConfigService;
import com.jxmcloud.business.cut.model.database.DBLogItem;
import com.jxmcloud.business.cut.model.database.DBUserBag;
import com.jxmcloud.business.cut.service.database.ILogItemDBService;
import com.jxmcloud.business.cut.service.database.IUserBagDBService;
import com.jxmcloud.business.cut.service.logic.IUserLiveHandle;
import com.jxmcloud.business.cut.service.user.IUserBagService;
import com.jxmcloud.business.cut.vo.json.ConfigGlobalGlobalVo;
import com.jxmcloud.business.cut.vo.json.ConfigItemVo;
import com.jxmcloud.business.cut.vo.user.PlayerInfoVo;
import com.jxmcloud.business.cut.vo.user.UserBagVo;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.*;

/**
 * 背包类接口层
 */
@Service
public class UserBagServiceImpl implements IUserBagService {
    @Resource
    private IUserBagDBService userBagDBService;

    @Resource
    private DataConfigGlobalGlobalLoader dataConfigGlobalGlobalLoader;
    @Resource
    private ILogItemDBService logItemDBService;
    @Resource
    private DataConfigService dataConfigService;
    @Resource
    private IUserLiveHandle userLiveHandle;

    @Override
    public boolean addItem(PlayerInfoVo player, Integer id, Integer count) {
        Integer itemCount = this.getItemCount(player, id);
        itemCount += count;
        //加背包缓存
        player.getBag().getBagList().put(id, itemCount);
        player.getMaster().getSaveList().add(CutSaveKey.MODEL_BAG);
        // 日志
        this.addItemLog(player, id, count);
        // 开启直播
        this.checkOpenLive(player, id, count);
        return true;
    }

    @Override
    public boolean revertAddItem(PlayerInfoVo player, Integer id, Integer count) {
        Integer itemCount = this.getItemCount(player, id);
        //回滚扣除
        itemCount -= count;
        //加背包缓存
        player.getBag().getBagList().put(id, itemCount);
        player.getMaster().getSaveList().add(CutSaveKey.MODEL_BAG);
        // 日志
        this.revertAddItemLog(player, id, count);
        // 开启直播
        this.checkOpenLive(player, id, count);
        return true;
    }

    @Override
    public void cleanBag(PlayerInfoVo player) {
        player.getBag().getBagList().clear();
        player.getMaster().getSaveList().add(CutSaveKey.MODEL_BAG);
    }

    @Override
    public void batchAddItem(PlayerInfoVo player, AccountItemDto accountItemDto) {
        List<ItemDto> itemList = accountItemDto.getItemList();
        for (ItemDto item : itemList) {
            this.addItem(player, item.getItemId(), item.getItemNum());
        }
    }

    @Override
    public boolean addAward(PlayerInfoVo player, BagInfoDto bagAward) {
        return this.addItem(player, bagAward.getId(), bagAward.getCount());
    }

    @Override
    public boolean delLotteryItem(PlayerInfoVo player) {
        Integer itemIdLottery = dataConfigGlobalGlobalLoader.getConfigGlobalGlobal().getItemIdLottery();
        return this.delItem(player, itemIdLottery, 1);
    }

    @Override
    public void addScorePool(PlayerInfoVo player, Integer addScore) {
        Integer poolItemId = dataConfigGlobalGlobalLoader.getConfigGlobalGlobal().getItemIdPool();
        // 加道具
        this.addItem(player, poolItemId, addScore);
    }

    @Override
    public Integer getScorePool(PlayerInfoVo player) {
        Integer poolItemId = dataConfigGlobalGlobalLoader.getConfigGlobalGlobal().getItemIdPool();
        return this.getItemCount(player, poolItemId);
    }

    @Override
    public boolean delItem(PlayerInfoVo player, Integer id, Integer count) {
        Integer itemCount = this.getItemCount(player, id);
        if (itemCount < count) {
            return false;
        } else if (itemCount.equals(count)) {
            player.getBag().getBagList().remove(id);
        } else {
            itemCount -= count;
            player.getBag().getBagList().put(id, itemCount);
        }
        player.getMaster().getSaveList().add(CutSaveKey.MODEL_BAG);
        // 日志
        this.addItemLog(player, id, 0 - count);
        return true;
    }

    @Override
    public Integer getItemCount(PlayerInfoVo player, Integer id) {
        Integer itemCount = player.getBag().getBagList().get(id);
        if (ObjectUtil.isNull(itemCount)) {
            return 0;
        }
        return itemCount;
    }

    @Override
    public boolean checkItemCount(PlayerInfoVo player, Integer id, Integer count) {
        Integer itemCount = this.getItemCount(player, id);
        if (itemCount < count) {
            return false;
        }
        return true;
    }

    @Override
    public List<BagInfoDto> packBagData(PlayerInfoVo player) {
        List<BagInfoDto> bagList = Lists.newArrayList();
        HashMap<Integer, Integer> map = player.getBag().getBagList();
        // 直接遍历Map
        for (Map.Entry<Integer, Integer> entry : map.entrySet()) {
            BagInfoDto bagInfoDto = new BagInfoDto();
            bagInfoDto.setId(entry.getKey());
            bagInfoDto.setCount(entry.getValue());
            bagList.add(bagInfoDto);
        }
        return bagList;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean saveToDb(PlayerInfoVo player, String key) {
        // 存储数据到数据
        if (key.equals(CutSaveKey.MODEL_BAG)) {
            String jsonStr = this.packBagStr(player);
            if (!jsonStr.isEmpty()) {
                userBagDBService.updateBag(player.getBase().getUid(), player.getActivity().getActivityId(), jsonStr);
            }
        }
        return true;
    }

    @Override
    public boolean loadFromDb(PlayerInfoVo player, Integer uid) {
        DBUserBag dbUserActivityInfo = userBagDBService.loadBag(uid, player.getActivity().getActivityId());
        // 从数据库加载数据
        if (!Objects.isNull(dbUserActivityInfo)) {
            JSONArray jsonArray = JSON.parseArray(dbUserActivityInfo.getBag());
            if (!jsonArray.isEmpty()) {
                HashMap<Integer, Integer> bagMap = new HashMap<>();
                for (int i = 0; i < jsonArray.size(); i++) {
                    JSONObject jsonObject = jsonArray.getJSONObject(i);
                    Long key = jsonObject.getLong("k");
                    Long value = jsonObject.getLong("v");
                    bagMap.put(key.intValue(), value.intValue());
                }
                player.getBag().setBagList(bagMap);
            }
            return true;
        }
        return false;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean register(PlayerInfoVo player, Integer uid) {
        String jsonStr = this.packBagStr(player);
        return userBagDBService.insertBag(player.getBase().getUid(), player.getActivity().getActivityId(), jsonStr);
    }

    /**
     * 打包背包数据为字符串
     *
     * @param player
     * @return
     */
    private String packBagStr(PlayerInfoVo player) {
        UserBagVo bag = player.getBag();
        HashMap<Integer, Integer> bagList = bag.getBagList();
        // 将HashMap转换为JSON字符串
        JSONArray jsonArray = new JSONArray();
        for (Map.Entry<Integer, Integer> entry : bagList.entrySet()) {
            JSONObject item = new JSONObject();
            item.put("k", entry.getKey());
            item.put("v", entry.getValue());
            jsonArray.add(item);
        }
        return jsonArray.toJSONString();
    }

    /**
     * 添加道具日志
     *
     * @param player
     * @param itemId
     * @param count
     * @return
     */
    private boolean addItemLog(PlayerInfoVo player, Integer itemId, Integer count) {
        // 是否需要写入日志
        ConfigItemVo itemConfig = dataConfigService.getConfigItemConfig(itemId);
        if (ObjectUtil.isNull(itemConfig)) {
            return false;
        }
        Integer record = itemConfig.getRecord();
        if (ObjectUtil.isNull(record) || record.equals(0)) {
            return false;
        }

        DBLogItem logItem = new DBLogItem();
        logItem.setUid(player.getBase().getUid());
        logItem.setItemId(itemId);
        logItem.setChangeCount(count);
        logItem.setActivityId(player.getActivity().getActivityId());
        logItem.setTime(new Date());

        return logItemDBService.insertData(logItem);
    }

    /**
     * 添加道具日志
     *
     * @param player
     * @param itemId
     * @param count
     * @return
     */
    private boolean revertAddItemLog(PlayerInfoVo player, Integer itemId, Integer count) {
        // 是否需要写入日志
        ConfigItemVo itemConfig = dataConfigService.getConfigItemConfig(itemId);
        if (ObjectUtil.isNull(itemConfig)) {
            return false;
        }
        Integer record = itemConfig.getRecord();
        if (ObjectUtil.isNull(record) || record.equals(0)) {
            return false;
        }

        DBLogItem logItem = new DBLogItem();
        logItem.setUid(player.getBase().getUid());
        logItem.setItemId(itemId);
        logItem.setChangeCount(count);
        logItem.setActivityId(player.getActivity().getActivityId());
        logItem.setTime(new Date());

        return logItemDBService.insertData(logItem);
    }

    /**
     * 检查道具是否开启直播
     *
     * @param player
     * @param itemId
     * @param count
     */
    private void checkOpenLive(PlayerInfoVo player, Integer itemId, Integer count) {
        if (count <= 0) {
            return;
        }
        ConfigGlobalGlobalVo globalConfig = dataConfigService.getConfigGlobalGlobalConfig();
        if (ObjectUtil.isNull(globalConfig)) {
            return;
        }
        if (!itemId.equals(globalConfig.getItemIdOpenLive())) {
            return;
        }
        userLiveHandle.createUserWatchLiveTaskDetail(player);
    }
}